#include "index_factory.h"
#include <faiss/IndexIDMap.h>
#include <faiss/IndexFlat.h>
#include "hnswlib_index.h"
#include "hnswlib/hnswlib.h"
void IndexFactory::init(IndexType type,int dim,int num_data,MetricType metric){
    faiss::MetricType faiss_metric=(metric==MetricType::L2)?faiss::MetricType::METRIC_L2:faiss::MetricType::METRIC_INNER_PRODUCT;
    switch (type){
        case IndexType::FLAT:
            index_map[type]=new FaissIndex(new faiss::IndexIDMap(new faiss::IndexFlat(dim,faiss_metric)));
            break;
        case IndexFactory::IndexType::HNSW:{
            index_map[type]=new HNSWLibIndex(dim,num_data,metric,16,200);
            break;
        }
        case IndexType::FILTER:{
            index_map[type]=new FilterIndex();
        }
        default:
            break;
    }
}

IndexFactory& IndexFactory::getGlobalIndexFactory(){
    //局部静态变量线程安全
    static IndexFactory factory;
    return factory;
}

void* IndexFactory::getIndex(IndexType type)const{
    auto it=index_map.find(type);
    if(it!=index_map.end()){
        return it->second;
    }
    return nullptr;
}

void IndexFactory::saveIndex(const std::string& folderPath,ScalarStorage& scalarStorage){
    for (const auto& index_entry:index_map)
    {
        IndexType index_type=index_entry.first;
        void* index=index_entry.second;

        //每个索引生成一个文件名
        std::string index_file_name=folderPath+"/"+std::to_string(static_cast<int>(index_type))+".index";
        if(index_type==IndexType::HNSW){
            static_cast<HNSWLibIndex*>(index)->saveIndex(index_file_name);
        }else if(index_type==IndexType::FLAT){
            static_cast<FaissIndex*>(index)->saveIndex(index_file_name);
        }else if(index_type==IndexType::FILTER){
            static_cast<FilterIndex*>(index)->saveIndex(scalarStorage,index_file_name);
        }
    }
    
}
void IndexFactory::loadIndex(const std::string& folderPath,ScalarStorage& scalarStorage){
    GlobalLogger->debug("loadIndex");
    for(const auto&index_entry:index_map){
        IndexType index_type=index_entry.first;
        void* index=index_entry.second;

        //生成文件名
        std::string index_file_name=folderPath+"/"+std::to_string(static_cast<int>(index_type))+".index";
        if(index_type==IndexType::HNSW){
            static_cast<HNSWLibIndex*>(index)->loadIndex(index_file_name);
        }else if(index_type==IndexType::FLAT){
            static_cast<FaissIndex*>(index)->loadIndex(index_file_name);
        }else if(index_type==IndexType::FILTER){
            static_cast<FilterIndex*>(index)->loadIndex(scalarStorage,index_file_name);
        }
    }
}